// ----------------------------------------------------------------------------------
// CallingLabVIEWBuiltDLLFromCPP.cpp : 
//
// Sample program to show how to call some simple functions in a LabVIEW built DLL.
// 
// NOTE: Look at ReadMe.txt for more information or how to setup this sample program.
// ----------------------------------------------------------------------------------

#include "../LabVIEW/Build/LabVIEWBuiltDLL.h"
#include <iostream>

static void CallUpperCaseString();
static void CallMultiplyArray();
static void CallErrorCluster();

static LStrHandle CreateLStrFromCStr(const char* cstr);
static void CreateCStrFromLStr(LStrHandle lstrIn, char* cstrBuffer, long bufLen);


int main(int argc, char* argv[])
{
	CallUpperCaseString();
	CallMultiplyArray();
	CallErrorCluster();
	system("pause");

	return 0;
}

static void CallUpperCaseString()
{
	char* stringIn = "hello world";

	const long bufferSize = 256;
	char strOutBuf[bufferSize];

	std::cout << "Calling UpperCaseString..." << std::endl;
	UpperCaseString(stringIn, strOutBuf, bufferSize);

	std::cout << "String In = " << stringIn << "\nString Out = " << strOutBuf << std::endl << std::endl;
}

static void CallMultiplyArray()
{
	const long nElts = 5;
	const long arraySize = sizeof(long) + nElts * sizeof(double);

	TD2Hdl arrayIn = (TD2Hdl)DSNewHClr(arraySize);
	if (!arrayIn) {
		std::cout << "ERROR: Not enough memory...";
		return;
	}

	TD2Hdl arrayOut = (TD2Hdl)DSNewHClr(arraySize);
	if (!arrayOut) {
		std::cout << "ERROR: Not enough memory...";
		DSDisposeHandle(arrayIn);
		return;
	}

	(*arrayIn)->dimSize = nElts;
	int32 ii;
	for (ii = 0; ii < nElts; ++ii)
		(*arrayIn)->Numeric[ii] = ii;

	std::cout << "Calling MultiplyArray..." << std::endl;
	MultiplyArray(&arrayIn, 10, &arrayOut);

	std::cout << "Array In\tArray Out\n";
	for (ii = 0; ii < nElts; ++ii)
		std::cout << (*arrayIn)->Numeric[ii] << "\t\t" << (*arrayOut)->Numeric[ii] << "\n";
	std::cout << std::endl;

	DSDisposeHandle(arrayIn);
	DSDisposeHandle(arrayOut);
	arrayIn = NULL;
	arrayOut = NULL;
}

static void CallErrorCluster()
{
	TD1 errorIn, errorOut;

	memset(&errorIn, 0, sizeof(errorOut));
	memset(&errorOut, 0, sizeof(errorOut));

	LStrHandle source = CreateLStrFromCStr("hello world");
	if (!source)
		return; // error

	errorIn.status = LVBooleanTrue;
	errorIn.code = mgArgErr;
	errorIn.source = source;

	std::cout << "Calling ErrorCluster..." << std::endl;
	ErrorCluster(&errorIn, &errorOut);

	char sourceIn[256], sourceOut[256];
	CreateCStrFromLStr(errorIn.source, sourceIn, 256);
	CreateCStrFromLStr(errorOut.source, sourceOut, 256);

	std::cout << "Error In\n";
	std::cout << "\tstatus = " << (errorIn.status ? "TRUE" : "FALSE") << "\n";
	std::cout << "\tcode = " << errorIn.code << "\n";
	std::cout << "\tsource = " << sourceIn << "\n" << std::endl;

	std::cout << "Error Out\n";
	std::cout << "\tstatus = " << (errorOut.status ? "TRUE" : "FALSE") << "\n";
	std::cout << "\tcode = " << errorOut.code << "\n";
	std::cout << "\tsource = " << sourceOut << "\n" << std::endl;

	DSDisposeHandle(errorIn.source);
	DSDisposeHandle(errorOut.source);
	errorIn.source = NULL;
	errorOut.source = NULL;
}

static LStrHandle CreateLStrFromCStr(const char* cstr)
{
	const long cstrLen = (long)strlen(cstr);

	const long lstrSize = sizeof(int32) + cstrLen;
	LStrHandle lstr = (LStrHandle)DSNewHClr(lstrSize);
	if (!lstr) {
		std::cout << "ERROR: Not enough memory...";
		return NULL;
	}

	LStrLen(*lstr) = cstrLen;
	memcpy(LStrBuf(*lstr), cstr, cstrLen);

	return lstr;
}

static void CreateCStrFromLStr(LStrHandle lstrIn, char* cstrBuffer, long bufLen)
{
	int32 len = LHStrLen(lstrIn);
	if (len >= bufLen)
		len = bufLen-1;

	memcpy(cstrBuffer, LHStrBuf(lstrIn), len);
	cstrBuffer[len] = 0;
}
